package com.hui.controller;

import com.hui.dto.LoginParamDTO;
import com.hui.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;

/**
 * @author chenlei
 * @description 登录
 * @date 2022/6/14
 */
@RestController
@Slf4j
@Api(tags = {"登录"})
public class LoginController {

    @Value("${spring.security.oauth2.token-url}")
    private String GET_TOKEN_URL;

    @Autowired
    private RestTemplate restTemplate;

    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result login(@RequestBody LoginParamDTO loginParamDTO) {

        // 判断为空
        if (StringUtils.isEmpty(loginParamDTO.getUsername())) {
            return new Result(HttpServletResponse.SC_FORBIDDEN, "请输入用户名", null);
        }
        if (StringUtils.isEmpty(loginParamDTO.getPassword())) {
            return new Result(HttpServletResponse.SC_FORBIDDEN, "请输入密码", null);
        }
        if (StringUtils.isEmpty(loginParamDTO.getCode())) {
            return new Result(HttpServletResponse.SC_FORBIDDEN, "请输入验证码", null);
        }

        if (StringUtils.isEmpty(loginParamDTO.getDateTime())) {
            return new Result(HttpServletResponse.SC_FORBIDDEN, "时间戳不能为空", null);
        }


        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        // 构建请求体（请求参数）
        MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
        paramsMap.add("username", loginParamDTO.getUsername());
        paramsMap.add("password", loginParamDTO.getPassword());
        paramsMap.add("grant_type", "password");

        //利用密码模式到sso授权服务器中拿到access_token和refresh_token，因为是同一个项目的模块，可以使用密码模式
        //在请求头中带上客户端的账号密码
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(paramsMap, headers);
        // 设置 Authorization
        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(loginParamDTO.getClientId(), loginParamDTO.getClientSecret()));

        ResponseEntity<OAuth2AccessToken> result;

        try {
            //发送请求,从TokenEndpoint类中可以看到返回值是OAuth2AccessToken
            result = restTemplate.postForEntity(GET_TOKEN_URL, entity, OAuth2AccessToken.class);
        } catch (HttpClientErrorException e) {
            log.error(e.getMessage());
            return new Result(HttpServletResponse.SC_FORBIDDEN, e.getMessage(), null);
        }

        //处理返回结果
        if (result.getStatusCode() != HttpStatus.OK) {
            return new Result(HttpServletResponse.SC_UNAUTHORIZED, "登录失败", null);
        }

        //在这里也可以使用vo对象，封装好前端需要的数据返回，这个token如果以前设置了token加强信息，这里也能获取到
        return new Result(HttpServletResponse.SC_OK, "登录成功", result.getBody());
    }

    @GetMapping("/exit")
    @ApiOperation("退出登录")
    @ResponseBody
    public Result logout(@RequestHeader("Authorization") String authorization) {
        try {
            // TODO 删除缓存中的refresh_token
            return Result.success("退出成功");
        } catch (Exception e) {
            log.error("退出登录失败：{}", e.getMessage());
            return Result.error(500, "退出登录失败", null);
        }
    }
}
